﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using TUCAMAPI;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using Eps.Ai.Common;
using System.Drawing;
using InfonavaEye.handler;
using System.Timers;
using InfonavaEye.model;
using Sylan.Common.Util;
using InfonavaEye.common;
using System.Linq;
using InfonavaEye.util;
using InfonavaEye.enums;
using InfonavaEye.Handler;
using System.ComponentModel;
using InfonavaEye.components;

namespace InfonavaEye.Forms
{
    public partial class OriginAdjustForm : Form
    {
        FocusDistanceCurrentLimiter focusDistanceCurrentLimiter;
        public event Action settingCloseDelegate;

        /// <summary>
        /// 默认坐标文本
        /// </summary>
        private string defaultXYZText = "0,0,0";

        /// <summary>
        /// 默认当前坐标
        /// </summary>
        private string defaultCurrentXYZText = "x,y,z";

        /// <summary>
        /// 校准原点的位置（x,y）
        /// </summary>
        public XYZ[] fixZeroLocation;

        public BoxModel boxModel;

        /// <summary>
        /// 钉盒倾斜角度
        /// </summary>
        public double boxAngle = -9999;

        private bool timerStoped = false;
        System.Timers.Timer readLocationTimer;   // The auto exposure timer

        private CameraHandler cameraHandler = CameraHandler.Instance;
        public PLCHandler plcHandler = PLCHandler.Instance;

        public OriginAdjustForm()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false; //加载时 取消跨线程检查
        }

        private void SamplePro_Load(object sender, EventArgs e)
        {
            this.lblNailShape.Text = this.boxModel.NailShape == 1 ? "脊柱钉类" : "创伤圆钉类";
            this.lblTemplateName.Text = this.boxModel.boxName;

            this.btnLeftDownLocation.DisabledForeColor = Color.Gray;
            this.btnLeftUpLocation.DisabledForeColor = Color.Gray;
            this.btnRightDownLocation.DisabledForeColor = Color.Gray;
            this.btnLeftDownLocation.DisabledBackColor = Color.FromArgb(255, 200, 200, 200);
            this.btnLeftUpLocation.DisabledBackColor = Color.FromArgb(255, 200, 200, 200);
            this.btnRightDownLocation.DisabledBackColor = Color.FromArgb(255, 200, 200, 200);

            this.lblCurrentXYZ.Text = defaultCurrentXYZText;
            int drawingBoxWidth = drawingBox.Width;
            drawingBox.Width = (int)(drawingBox.Height / 2048f * 3072f);
            drawingBox.Location = new Point(drawingBox.Location.X + (drawingBoxWidth - drawingBox.Width) / 2, drawingBox.Location.Y);
            this.btnSure.Enabled = true;
            initPicCursor();

            #region 坐标计算
            this.lblLeftUpLocation.Text = defaultXYZText;
            this.lblRightDownLocation.Text = defaultXYZText;
            this.lblCurrentXYZ.Text = defaultCurrentXYZText;
            if (this.boxModel.boxAngle != -9999)
            {
                this.boxAngle = this.boxModel.boxAngle;
                this.lblBoxAngle.Text = this.boxAngle.ToString();
            }
            
            this.parseAreaXYZ();
            #endregion

            //btnSure.Text = "移动中";
            ThreadHelper.ExcuteThreadTask(() =>
            {
                cameraHandler.initCompleteDelegate += CameraHandler_initCompleteDelegate;
                plcHandler.PLCInitCompleteDelegate += PLCHandler_PLCInitCompleteDelegate;
                focusDistanceCurrentLimiter = new FocusDistanceCurrentLimiter();
                plcHandler.StartPLC();
                cameraHandler.play(this.drawingBox);
            }, 100);
        }

        private void CameraHandler_initCompleteDelegate()
        {
            cameraHandler.initCompleteDelegate -= CameraHandler_initCompleteDelegate;
            this.Invoke(new Action(() =>
            {
                this.btnLeftUpLocate.Visible = true;
                this.btnLeftDownLocate.Visible = true;
                this.btnRightDownLocate.Visible = true;
            }));
        }

        private void SamplePro_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (readLocationTimer != null)
            {
                Console.WriteLine("readLocationTimer 关闭");
                timerStoped = true;
                readLocationTimer.Stop();
                readLocationTimer.Close();
            }

            if (plcHandler != null)
            {
                plcHandler.PLCInitCompleteDelegate -= PLCHandler_PLCInitCompleteDelegate;
            }
            
            if (cameraHandler != null) {
                this.cameraHandler.pause();//暂停视频
                cameraHandler.initCompleteDelegate -= CameraHandler_initCompleteDelegate;
            }

            if (settingCloseDelegate != null)
            {
                settingCloseDelegate.Invoke();
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            if (cameraHandler.isCameraOpening) {
                e.Cancel = true; //取消关闭操作
                MessageBox.Show("相机正在连接中，无法中断，请稍后再尝试关闭","提示",MessageBoxButtons.OK);
            }
        }

        private void PLCHandler_PLCInitCompleteDelegate()
        {
            plcHandler.PLCInitCompleteDelegate -= PLCHandler_PLCInitCompleteDelegate;
            InitAllTimers();
            this.Invoke(new Action(() =>
            {
                this.btnBack.Visible = true;
                this.btnSure.Visible = true;
            }));
        }

        /// <summary>
        /// 计算区域4个角的坐标
        /// </summary>
        /// <summary>
        /// 计算区域4个角的坐标
        /// </summary>
        private void parseAreaXYZ()
        {
            if (this.boxModel == null || this.boxModel.boxAreas == null || this.boxModel.boxAreas.Count == 0)
            {
                AutoCloseMessageBox.Show("检查到钉盒模板没有配置区域，请重新建模");
                return;
            }
            if (this.boxModel.boxAngle == -9999)
            {
                AutoCloseMessageBox.Show("检查到钉盒模板没有设置钉盒倾斜角度，请重新建模");
                return;
            }
            var boxArea = this.boxModel.boxAreas[0];
            var rowCount = boxArea.rowCount;
            var columnCount = boxArea.columnCount;
            var startPoint = boxArea.startPoint;
            var holdPitch = boxArea.holdPitch;
            if (startPoint == null)
            {
                AutoCloseMessageBox.Show("检查到钉盒模板没有设置第一个区域的起点，请重新建模");
                return;
            }
            if (rowCount == 0)
            {
                AutoCloseMessageBox.Show("检查到钉盒模板没有设置第一个区域的行数，请重新建模");
                return;
            }
            if (columnCount == 0)
            {
                AutoCloseMessageBox.Show("检查到钉盒模板没有设置第一个区域的列数，请重新建模");
                return;
            }
            if (holdPitch == null)
            {
                AutoCloseMessageBox.Show("检查到钉盒模板没有设置第一个区域的孔距数据，请重新建模");
                return;
            }

            var x = startPoint[0];
            var y = startPoint[1];
            var z = startPoint[2];
            var xPitch = holdPitch[0];
            var yPitch = holdPitch[1];

            var rightDownPoint = new int[] { x, y, z };
            this.lblRightDownLocation.Text = String.Join(",", rightDownPoint);

            if (this.boxAngle != -9999)
            {
                //以右下角为基础点，计算左下角。
                var leftDownPoint = new int[] {
                    (int)(x + xPitch * (columnCount - 1) * Math.Cos(this.boxAngle * Math.PI / 180)),
                    (int)(y + xPitch * (columnCount - 1) * Math.Sin(this.boxAngle * Math.PI / 180)),
                    z,
                };
                this.lblLeftDownLocation.Text = String.Join(",", leftDownPoint);

                //以坐下角为基础点，计算左上角
                var leftUpPoint = new int[] {
                    (int)(leftDownPoint[0] + yPitch * (rowCount - 1)* Math.Cos((90-this.boxAngle)* Math.PI / 180)),
                    (int)(leftDownPoint[1] + yPitch * (rowCount - 1)* Math.Sin((90-this.boxAngle) *Math.PI / 180)),
                    z,
                };
                this.lblLeftUpLocation.Text = String.Join(",", leftUpPoint);
            }
        }

        private void moveToFirstNail()
        {
            if (this.boxModel == null || this.plcHandler == null) return;
            if (this.boxModel.boxAreas != null && this.boxModel.boxAreas.Count > 0)
            {
                var area = this.boxModel.boxAreas[0];
                if (area.startPoint != null)
                {
                    plcHandler.moveToXYZandCapture(area.startPoint[0], area.startPoint[1], area.startPoint[2], false);
                    btnSure.Enabled = true;
                    btnSure.Text = "开始识别";
                }
            }
        }

        private void SamplePro_Resize(object sender, EventArgs e)
        {
            drawingBox.Refresh();
        }

        private void InitAllTimers()
        {
            readLocationTimer = new System.Timers.Timer(500);
            readLocationTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerReadLocation);
            readLocationTimer.AutoReset = true;
            readLocationTimer.SynchronizingObject = this;
            readLocationTimer.Start();
        }

        private void OnTimerReadLocation(object sender, ElapsedEventArgs e)
        {
            readLocationTimer.Stop();
            this.readXYZ();
            if (!timerStoped)
            {
                readLocationTimer.Start();
            }
        }

        private int[] readXYZ()
        {
            try
            {
                Console.WriteLine("readXYZ OriginAdjust");
                int[] xyz = plcHandler.readCurrentXYZ();// new int[] { 200, 300, 500 };// 
                lblCurrentXYZ.Text = String.Format("{0},{1},{2}", xyz[0], xyz[1], xyz[2]);
                Console.WriteLine("读取到当前坐标：{0}", lblCurrentXYZ.Text);
                return xyz;
            }
            catch (Exception ex)
            {
                //AutoCloseMessageBox.Show(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// 计算电机速度
        /// </summary>
        /// //shape (1.脊柱钉类 2.创伤圆钉类 ,3.板棒类)
        private void calcSpeed(int shape) {
            switch(shape) {
                case 1:
                    //脊柱钉
                    this.boxModel.SpeedX = Config.SPINE_MOTOR_SPEED_X;
                    this.boxModel.SpeedY = Config.SPINE_MOTOR_SPEED_Y;
                    break;
                case 2:
                    //创伤类
                    this.boxModel.SpeedX = Config.TRAUMA_MOTOR_SPEED_X;
                    this.boxModel.SpeedY = Config.TRAUMA_MOTOR_SPEED_Y;
                    break;
                default:
                    this.boxModel.SpeedX = Config.MOTOR_DEFAULT_SPEED;
                    this.boxModel.SpeedY = Config.MOTOR_DEFAULT_SPEED;
                    break;
            } 
        }

        private void btnSure_Click(object sender, EventArgs e)
        {
            if (cameraHandler.isCameraOpening)
            {
                MessageBox.Show("相机正在连接中，无法中断，请稍后尝试", "提示", MessageBoxButtons.OK);
                return;
            }

            /*if (m_opCamList.Count > 0)
            {
                StopWaitForFrame(m_opCamList[m_indexCam]);
            }*/

            this.calcSpeed(this.boxModel.NailShape);
            try
            {
                var rightDownLocation = lblRightDownLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
                var leftUpLocation = lblLeftUpLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
                var leftDownLocation = lblLeftDownLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
                this.fixZeroLocation = new XYZ[]{ new XYZ
                {
                    X = rightDownLocation[0],
                    Y = rightDownLocation[1],
                    Z = rightDownLocation[2],
                } ,
                new XYZ
                {
                    X = leftUpLocation[0],
                    Y = leftUpLocation[1],
                    Z = leftUpLocation[2],
                },
                new XYZ
                {
                    X = leftDownLocation[0],
                    Y = leftDownLocation[1],
                    Z = leftDownLocation[2],
                }
                };

                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            catch (Exception ex) { 
               Console.WriteLine("{0},{1}",ex.Message,ex.StackTrace);
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            if (cameraHandler.isCameraOpening)
            {
                MessageBox.Show("相机正在连接中，无法中断，请稍后尝试", "提示", MessageBoxButtons.OK);
                return;
            }

            this.Close();
        }

        private void lblCurrentXYZ_Click(object sender, EventArgs e)
        {

        }

        #region 图像参考线
        private void initPicCursor()
        {

            /*PictureBox xCrossLine = new PictureBox();
            PictureBox xCrossLine1 = new PictureBox();
            PictureBox xCrossLine2 = new PictureBox();
            PictureBox yCrossLine = new PictureBox();
            PictureBox yCrossLine1 = new PictureBox();
            PictureBox yCrossLine2 = new PictureBox();*/

            //圆型的最佳大小
            var marginTop = 40;
            var nailBestWidthOnView = drawingBox.Height - marginTop * 2;
            var nailBestHeightOnView = drawingBox.Height - marginTop * 2;
            var marginLeft = (drawingBox.Width - nailBestWidthOnView) / 2;

            xCrossLine.BackColor = System.Drawing.Color.Red;
            xCrossLine.TabStop = false;
            xCrossLine.Width = drawingBox.Width - 2 * marginLeft;
            xCrossLine.Height = 1;
            xCrossLine.Location = new Point(drawingBox.Location.X + marginLeft, drawingBox.Location.Y + marginTop);

            xCrossLine1.BackColor = System.Drawing.Color.Red;
            xCrossLine1.TabStop = false;
            xCrossLine1.Width = drawingBox.Width - 2 * marginLeft;
            xCrossLine1.Height = 1;
            xCrossLine1.Location = new Point(drawingBox.Location.X + marginLeft, drawingBox.Location.Y + drawingBox.Height / 2);

            xCrossLine2.BackColor = System.Drawing.Color.Red;
            xCrossLine2.TabStop = false;
            xCrossLine2.Width = drawingBox.Width - 2 * marginLeft;
            xCrossLine2.Height = 1;
            xCrossLine2.Location = new Point(drawingBox.Location.X + marginLeft, drawingBox.Location.Y + drawingBox.Height - marginTop);

            ////Y
            yCrossLine.BackColor = System.Drawing.Color.Red;
            yCrossLine.TabStop = false;
            yCrossLine.Width = 1;
            yCrossLine.Height = drawingBox.Height - 2 * marginTop;
            yCrossLine.Location = new Point(drawingBox.Location.X + (drawingBox.Width - nailBestWidthOnView) / 2, drawingBox.Location.Y + marginTop);

            yCrossLine1.BackColor = System.Drawing.Color.Red;
            yCrossLine1.TabStop = false;
            yCrossLine1.Width = 1;
            yCrossLine1.Height = drawingBox.Height - 2 * marginTop;
            yCrossLine1.Location = new Point(drawingBox.Location.X + drawingBox.Width / 2, drawingBox.Location.Y + marginTop);

            yCrossLine2.BackColor = System.Drawing.Color.Red;
            yCrossLine2.TabStop = false;
            yCrossLine2.Width = 1;
            yCrossLine2.Height = drawingBox.Height - 2 * marginTop;
            yCrossLine2.Location = new Point(drawingBox.Location.X + (drawingBox.Width + nailBestWidthOnView) / 2, drawingBox.Location.Y + marginTop);

            /*  var rect = drawingBox.DisplayRectangle;
              Pen pp = new Pen(Color.FromArgb(255, 0, 77, 203));
              drawingBox.CreateGraphics().DrawRectangle(pp, rect.X, rect.Y, rect.X + rect.Width - 1, rect.Y + rect.Height - 1);*/

            /*this.Controls.Add(xCrossLine);
            this.Controls.Add(xCrossLine1);
            this.Controls.Add(xCrossLine2);
            this.Controls.Add(yCrossLine);
            this.Controls.Add(yCrossLine1);
            this.Controls.Add(yCrossLine2);*/

            /* xCrossLine.Visible = false;
             yCrossLine.Visible = false;*/
        }
        #endregion

        private void drawingBox_Paint(object sender, PaintEventArgs e)
        {
            /*PictureBox p = (PictureBox)sender;
            Pen pp = new Pen(Color.FromArgb(255, 0, 77, 203));
            e.Graphics.DrawRectangle(pp, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.X + e.ClipRectangle.Width - 1, e.ClipRectangle.Y + e.ClipRectangle.Height - 1);*/
        }

        private void btnLeftUpLocation_Click(object sender, EventArgs e)
        {
            if (checkCurrentXYZ())
            {
                this.lblLeftUpLocation.Text = this.lblCurrentXYZ.Text;
            }
        }

        private bool checkCurrentXYZ()
        {
            if (defaultCurrentXYZText.Equals(this.lblCurrentXYZ.Text))
            {
                AutoCloseMessageBox.Show("当前坐标没有数据");
                return false;
            }
            return true;
        }

        private void btnLeftUpLocate_Click(object sender, EventArgs e)
        {
            if (defaultXYZText.Equals(this.lblLeftUpLocation.Text))
            {
                AutoCloseMessageBox.Show("请填入区域左上位置的坐标");
                return;
            }
            var leftUpPoint = this.lblLeftUpLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
            if (leftUpPoint.Length < 3)
            {
                AutoCloseMessageBox.Show("区域左上位置坐标数据不正常");
                return;
            }
            //leftUpPoint = new int[] { 17173, 127, 6901};
            toggleButtonStatus(1);
            this.moveToPoint(leftUpPoint);
        }

        private void btnRightDownLocate_Click(object sender, EventArgs e)
        {
            if (defaultXYZText.Equals(this.lblRightDownLocation.Text))
            {
                AutoCloseMessageBox.Show("请填入区域右下位置的坐标");
                return;
            }
            var rightDownPoint = this.lblRightDownLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
            if (rightDownPoint.Length < 3)
            {
                AutoCloseMessageBox.Show("区域右下位置坐标数据不正常");
                return;
            }
            //rightDownPoint = new int[] { 1043, -1641, 6901 };
            toggleButtonStatus(3);
            this.moveToPoint(rightDownPoint);
        }

        private void btnLeftDownLocate_Click(object sender, EventArgs e)
        {
            if (defaultXYZText.Equals(this.lblLeftDownLocation.Text))
            {
                AutoCloseMessageBox.Show("请填入区域左下位置的坐标");
                return;
            }
            var leftDownPoint = this.lblLeftDownLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
            if (leftDownPoint.Length < 3)
            {
                AutoCloseMessageBox.Show("区域左下位置坐标数据不正常");
                return;
            }
            //leftDownPoint = new int[] { 17173, -1577, 6901 };
            toggleButtonStatus(2);
            this.moveToPoint(leftDownPoint);
        }

        /// <summary>
        /// 切换按钮状态(参数 what : 1 左上，2.左下，3.右下,0.没有按下按钮)
        /// </summary>
        /// <param name="what"> 1 左上，2.左下，3.右下,0.没有按下按钮</param>
        private void toggleButtonStatus(int what)
        {
            this.btnLeftUpLocate.Enabled = what == 0 ;
            this.btnLeftUpLocate.Text = what == 1 ? "移动中" : "移动到这个点";

            this.btnLeftDownLocate.Enabled = what == 0 ;
            this.btnLeftDownLocate.Text = what == 2 ? "移动中" : "移动到这个点";

            this.btnRightDownLocate.Enabled = what == 0;
            this.btnRightDownLocate.Text = what == 3 ? "移动中" : "移动到这个点";

            this.btnRightDownLocation.Enabled = what == 0;
            this.btnLeftDownLocation.Enabled = what == 0;
            this.btnLeftUpLocation.Enabled = what == 0;
        }

        bool moving = false;
        private void moveToPoint(int[] point)
        {
            if (point == null || point.Length == 0)
            {
                AutoCloseMessageBox.Show("坐标不正确");
                return;
            }

            if (moving) return;

            ThreadHelper.ExcuteThreadTask(() =>
            {
                timerStoped = true;
                readLocationTimer.Stop();
                btnSure.Enabled = false;
                btnSure.Text = "移动中";
                try
                {
                    plcHandler.moveToXYZandCapture(point[0], point[1], point[2], false);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                finally
                {
                    moving = false;
                    timerStoped = false;
                    readLocationTimer.Start();
                    btnSure.Enabled = true;
                    btnSure.Text = "开始识别";
                    toggleButtonStatus(0);
                }
            });
        }

        private void btnRightDownLocation_Click(object sender, EventArgs e)
        {
            if (checkCurrentXYZ())
            {
                this.lblRightDownLocation.Text = this.lblCurrentXYZ.Text;
            }
        }

        private void btnLeftDownLocation_Click(object sender, EventArgs e)
        {
            if (checkCurrentXYZ())
            {
                this.lblLeftDownLocation.Text = this.lblCurrentXYZ.Text;
                this.calcBoxAngle();
            }
        }

        private void calcBoxAngle()
        {
            if (defaultXYZText.Equals(this.lblLeftDownLocation.Text))
            {
                return;
            }
            if (defaultXYZText.Equals(this.lblRightDownLocation.Text))
            {
                return;
            }

            var rightDownPoint = this.lblRightDownLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
            //var leftUpPoint = this.lblLeftUpLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
            var leftDownPoint = this.lblLeftDownLocation.Text.Split(new char[] { ',' }).Select(p => int.Parse(p)).ToArray();
            if (rightDownPoint.Length < 3 || leftDownPoint.Length < 3)
            {
                return;
            }

            this.boxAngle = MathUtil.anglevalue(rightDownPoint[0], rightDownPoint[1], leftDownPoint[0], leftDownPoint[1]);//校准前的对角线的角度
            this.boxAngle = Math.Round(this.boxAngle, 4, MidpointRounding.AwayFromZero);//保留4位小数
            this.lblBoxAngle.Text = this.boxAngle.ToString();
        }

        private void btnRefreshPic_Click(object sender, EventArgs e)
        {
            ThreadHelper.ExcuteThreadTask(() =>
            {
                this.cameraHandler.play(this.drawingBox);
            });
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }
    }
}

